home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / pyshared / rdflib / Collection.py < prev    next >
Encoding:
Python Source  |  2009-03-04  |  7.8 KB  |  261 lines

  1. from rdflib import RDF, BNode, Literal
  2. from rdflib.Graph import Graph
  3.  
  4. class Collection(object):
  5.     """
  6.     See 3.3.5 Emulating container types: http://docs.python.org/ref/sequence-types.html#l2h-232
  7.  
  8.     >>> from rdflib.BNode import BNode
  9.     >>> from rdflib.Literal import Literal
  10.     >>> from rdflib.Graph import Graph    
  11.     >>> listName = BNode()
  12.     >>> g = Graph('IOMemory')
  13.     >>> listItem1 = BNode()
  14.     >>> listItem2 = BNode()
  15.     >>> g.add((listName,RDF.first,Literal(1)))
  16.     >>> g.add((listName,RDF.rest,listItem1))
  17.     >>> g.add((listItem1,RDF.first,Literal(2)))
  18.     >>> g.add((listItem1,RDF.rest,listItem2))
  19.     >>> g.add((listItem2,RDF.rest,RDF.nil))
  20.     >>> g.add((listItem2,RDF.first,Literal(3)))
  21.     >>> c=Collection(g,listName)
  22.     >>> print list(c)
  23.     [rdflib.Literal(u'1', datatype=rdflib.URIRef('http://www.w3.org/2001/XMLSchema#integer')), rdflib.Literal(u'2', datatype=rdflib.URIRef('http://www.w3.org/2001/XMLSchema#integer')), rdflib.Literal(u'3', datatype=rdflib.URIRef('http://www.w3.org/2001/XMLSchema#integer'))]
  24.     >>> 1 in c
  25.     True
  26.     >>> len(c)
  27.     3
  28.     >>> c._get_container(1) == listItem1
  29.     True
  30.     >>> c.index(Literal(2)) == 1
  31.     True
  32.     """
  33.     def __init__(self, graph, uri, seq=[]):
  34.         self.graph = graph
  35.         self.uri = uri or BNode()
  36.         for item in seq:
  37.             self.append(item)
  38.  
  39.     def n3(self):
  40.         """
  41.         >>> from rdflib.BNode import BNode
  42.         >>> from rdflib.Literal import Literal
  43.         >>> from rdflib.Graph import Graph    
  44.         >>> listName = BNode()
  45.         >>> g = Graph('IOMemory')
  46.         >>> listItem1 = BNode()
  47.         >>> listItem2 = BNode()
  48.         >>> g.add((listName,RDF.first,Literal(1)))
  49.         >>> g.add((listName,RDF.rest,listItem1))
  50.         >>> g.add((listItem1,RDF.first,Literal(2)))
  51.         >>> g.add((listItem1,RDF.rest,listItem2))
  52.         >>> g.add((listItem2,RDF.rest,RDF.nil))
  53.         >>> g.add((listItem2,RDF.first,Literal(3)))
  54.         >>> c=Collection(g,listName)
  55.         >>> print c.n3()
  56.         ( "1"^^<http://www.w3.org/2001/XMLSchema#integer> "2"^^<http://www.w3.org/2001/XMLSchema#integer> "3"^^<http://www.w3.org/2001/XMLSchema#integer> )
  57.         """
  58.         return "( %s )"%(' '.join([i.n3() for i in self]))
  59.  
  60.     def _get_container(self, index):
  61.         """Gets the first, rest holding node at index."""
  62.         assert isinstance(index, int)
  63.         graph = self.graph
  64.         container = self.uri
  65.         i = 0
  66.         while i<index:
  67.             i += 1
  68.             container = graph.value(container, RDF.rest)
  69.             if container is None:
  70.                 break
  71.         return container
  72.  
  73.     def __len__(self):
  74.         """length of items in collection."""
  75.         count = 0
  76.         links=set()
  77.         for item in self.graph.items(self.uri):
  78.             assert item not in links,"There is a loop in the RDF list! (%s has been processed before)"%item
  79.             links.add(item)
  80.             count += 1
  81.         return count
  82.  
  83.     def index(self, item):
  84.         """
  85.         Returns the 0-based numerical index of the item in the list          
  86.         """
  87.         listName = self.uri
  88.         index = 0
  89.         while True:
  90.             if (listName,RDF.first,item) in self.graph:
  91.                 return index
  92.             else:
  93.                 newLink = list(self.graph.objects(listName,RDF.rest))
  94.                 index += 1
  95.                 if newLink == [RDF.nil]:
  96.                     raise ValueError("%s is not in %s"%(item,self.uri))
  97.                 elif not newLink:
  98.                     raise Exception("Malformed RDF Collection: %s"%self.uri)
  99.                 else:
  100.                     assert len(newLink)==1, "Malformed RDF Collection: %s"%self.uri
  101.                     listName = newLink[0]
  102.  
  103.     def __getitem__(self, key):
  104.         """TODO"""
  105.         c = self._get_container(key)
  106.         if c:
  107.             v = self.graph.value(c, RDF.first)
  108.             if v:
  109.                 return v
  110.             else:
  111.                 raise KeyError, key
  112.         else:
  113.             raise IndexError, key
  114.  
  115.     def __setitem__(self, key, value):
  116.         """TODO"""
  117.         c = self._get_container(key)
  118.         if c:
  119.             self.graph.add((c, RDF.first, value))
  120.         else:
  121.             raise IndexError, key
  122.  
  123.  
  124.     def __delitem__(self, key):
  125.         """
  126.         >>> from rdflib import RDF, RDFS
  127.         >>> from pprint import pformat
  128.         >>> g=Graph()
  129.         >>> a=BNode('foo')
  130.         >>> b=BNode('bar')
  131.         >>> c=BNode('baz')
  132.         >>> g.add((a,RDF.first,RDF.type))
  133.         >>> g.add((a,RDF.rest,b))
  134.         >>> g.add((b,RDF.first,RDFS.label))
  135.         >>> g.add((b,RDF.rest,c))
  136.         >>> g.add((c,RDF.first,RDFS.comment))
  137.         >>> g.add((c,RDF.rest,RDF.nil))
  138.         >>> len(g)
  139.         6
  140.         >>> def listAncestry(node,graph):
  141.         ...   for i in graph.subjects(RDF.rest,node): 
  142.         ...     yield i
  143.         >>> [str(node.n3()) for node in g.transitiveClosure(listAncestry,RDF.nil)]
  144.         ['_:baz', '_:bar', '_:foo']
  145.         >>> lst=Collection(g,a)
  146.         >>> len(lst)
  147.         3
  148.         >>> b==lst._get_container(1)
  149.         True
  150.         >>> c==lst._get_container(2)
  151.         True
  152.         >>> del lst[1]
  153.         >>> len(lst)
  154.         2
  155.         >>> len(g)
  156.         4
  157.         
  158.         """
  159.         self[key] # to raise any potential key exceptions
  160.         graph = self.graph
  161.         current = self._get_container(key)
  162.         assert current
  163.         if len(self)==1 and key>0:
  164.             pass
  165.         elif key==len(self)-1:
  166.             #the tail
  167.             priorLink = self._get_container(key-1)
  168.             self.graph.set((priorLink,RDF.rest,RDF.nil))
  169.             graph.remove((current, None, None))
  170.         else:
  171.             next = self._get_container(key+1)
  172.             prior = self._get_container(key-1)
  173.             assert next and prior
  174.             graph.remove((current, None, None))
  175.             graph.set((prior, RDF.rest, next))
  176.  
  177.     def __iter__(self):
  178.         """Iterator over items in Collections"""
  179.         return self.graph.items(self.uri)
  180.  
  181.     def append(self, item):
  182.         """
  183.         >>> from rdflib.Graph import Graph    
  184.         >>> listName = BNode()
  185.         >>> g = Graph()
  186.         >>> c=Collection(g,listName,[Literal(1),Literal(2)])
  187.         >>> links = [list(g.subjects(object=i,predicate=RDF.first))[0] for i in c]
  188.         >>> len([i for i in links if (i,RDF.rest,RDF.nil) in g])
  189.         1
  190.         
  191.         """
  192.         container = self.uri
  193.         graph = self.graph
  194.         #iterate to the end of the linked list
  195.         rest = graph.value(container, RDF.rest)
  196.         while rest:
  197.             if rest == RDF.nil:
  198.                 #the end, append to the end of the linked list
  199.                 node = BNode()
  200.                 graph.set((container, RDF.rest, node))
  201.                 container=node                
  202.                 break
  203.             else:
  204.                 #move down one link
  205.                 if container != self.uri:
  206.                     rest = graph.value(rest, RDF.rest)
  207.                 if not rest == RDF.nil:
  208.                     container=rest
  209.         graph.add((container, RDF.first, item))
  210.         graph.add((container, RDF.rest, RDF.nil))
  211.  
  212.     def clear(self):
  213.         container = self.uri
  214.         graph = self.graph
  215.         while container:
  216.             rest = graph.value(container, RDF.rest)
  217.             graph.remove((container, RDF.first, None))
  218.             graph.remove((container, RDF.rest, None))
  219.             container = rest
  220. def test():
  221.     import doctest
  222.     doctest.testmod()
  223.  
  224. if __name__=="__main__":
  225.     test()
  226.  
  227.     g = Graph()
  228.  
  229.     c = Collection(g, BNode())
  230.  
  231.     assert len(c)==0
  232.  
  233.     c = Collection(g, BNode(), [Literal("1"), Literal("2"), Literal("3"), Literal("4")])
  234.  
  235.     assert len(c)==4
  236.  
  237.     assert c[1]==Literal("2"), c[1]
  238.  
  239.     del c[1]
  240.  
  241.     assert list(c)==[Literal("1"), Literal("3"), Literal("4")], list(c)
  242.  
  243.     try:
  244.         del c[500]
  245.     except IndexError, i:
  246.         pass
  247.  
  248.     c.append(Literal("5"))
  249.  
  250.     print list(c)
  251.  
  252.     for i in c:
  253.         print i
  254.  
  255.     del c[3]
  256.  
  257.     c.clear()
  258.  
  259.     assert len(c)==0
  260.  
  261.